/*
 * Copyright (c) Jiandong.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */


import { ArkExecutor } from './arkexecutor/ArkExecutor';
import hilog from '@ohos.hilog';
import { SurfaceDelegate } from './common/SurfaceDelegate';
import { ReactNativeHost } from './ReactNativeHost';
import { ArkExecutorFactory } from './arkexecutor/ArkExecutorFactory';
import { JSCExecutorFactory } from './jscexecutor/JSCExecutorFactory';
import { HermesExecutorFactory } from '../hermes/reactexecutor/HermesExecutorFactory';
import { HermesExecutor } from '../hermes/reactexecutor/HermesExecutor';
import { JSCExecutor } from './jscexecutor/JSCExecutor';
import { UIImplementationProvider } from './uimanager/UIImplementationProvider'
import { JavaScriptExecutorFactory } from './bridge/JavaScriptExecutorFactory'
import { JSBundleLoader } from './bridge/JSBundleLoader'
import { ReactInstanceManager } from './ReactInstanceManager'
import { JSIModulePackage } from './bridge/JSIModulePackage'
import { JSInterpreter } from './JSInterpreter'
import { SurfaceDelegateFactory } from './common/SurfaceDelegateFactory'
import { ReactContext } from './bridge/ReactContext'

export class ReactInstanceManagerServiceBuilder {
  private static readonly TAG: string = "ReactInstanceManagerServiceBuilder";
  private mContext: any;
  private mJSBundleAssetUrl?: string;
  private mJSBundleLoader?: JSBundleLoader;
  private mJSMainModulePath?: string;
  private mUIImplementationProvider?: UIImplementationProvider;
  private mJavaScriptExecutorFactory?: JavaScriptExecutorFactory;
  private mJSIModulesPackage?: JSIModulePackage;
  private mSurfaceDelegateFactory?: SurfaceDelegateFactory;
  private jsInterpreter: JSInterpreter;

  constructor() {
    hilog.info(0x0000, ReactInstanceManagerServiceBuilder.TAG, 'constructor');
    this.jsInterpreter = JSInterpreter.OLD_LOGIC
  }

  public static getDefaultJSBundleFile(): string | null {
    return null;
  }

  public static getDefaultBundleResourceName(): string | null {
    return "index.harmony.bundle";
  }

  public setAbilityContext(context: any) {
    this.mContext = context
  }

  public setUIImplementationProvider(uiImplementationProvider?: UIImplementationProvider): ReactInstanceManagerServiceBuilder {
    this.mUIImplementationProvider = uiImplementationProvider;
    return this;
  }

  public setJSIModulesPackage(jsiModulePackage: JSIModulePackage): ReactInstanceManagerServiceBuilder {
    this.mJSIModulesPackage = jsiModulePackage;
    return this;
  }

  public setJavaScriptExecutorFactory(javaScriptExecutorFactory?: JavaScriptExecutorFactory): ReactInstanceManagerServiceBuilder {
    this.mJavaScriptExecutorFactory = javaScriptExecutorFactory;
    return this;
  }

  public setBundleResourceName(bundleResourceName: string): ReactInstanceManagerServiceBuilder {
    this.mJSBundleAssetUrl = bundleResourceName ? "assets://" + bundleResourceName : bundleResourceName
    this.mJSBundleLoader = null;
    return this;
  }

  public setJSBundleFile(jsBundleFile: string): ReactInstanceManagerServiceBuilder {
    if (jsBundleFile?.startsWith("assets://")) {
      this.mJSBundleAssetUrl = jsBundleFile;
      this.mJSBundleLoader = null;
      return this;
    } else {
      return this.setJSBundleLoader(JSBundleLoader.createDirectRunLoader(null, null, null));
    }
  }

  public setJSBundleLoader(jsBundleLoader: JSBundleLoader): ReactInstanceManagerServiceBuilder {
    this.mJSBundleLoader = jsBundleLoader;
    this.mJSBundleAssetUrl = null;
    return this;
  }

  public setJsEngineAsHermes(hermesEnabled: boolean): ReactInstanceManagerServiceBuilder {
    if (hermesEnabled) {
      this.setJSEngine(JSInterpreter.HERMES);
    } else {
      this.setJSEngine(JSInterpreter.JSC);
    }
    return this;
  }

  public setJsEngineAsArk(arkEnabled: boolean): ReactInstanceManagerServiceBuilder {
    if (arkEnabled) {
      this.setJSEngine(JSInterpreter.ARK);
    } else {
      this.setJSEngine(JSInterpreter.JSC);
    }
    return this;
  }


  public setJSMainModulePath(jsMainModulePath: string): ReactInstanceManagerServiceBuilder {
    this.mJSMainModulePath = jsMainModulePath;
    return this;
  }

  public setSurfaceDelegateFactory(surfaceDelegateFactory: SurfaceDelegateFactory): ReactInstanceManagerServiceBuilder {
    this.mSurfaceDelegateFactory = surfaceDelegateFactory;
    return this;
  }

  public getDefaultSurfaceDelegateFactory(): SurfaceDelegateFactory | null {
    return (() => {
      return new class SubClazz extends SurfaceDelegateFactory {
        public createSurfaceDelegate(var1: string): SurfaceDelegate | null {
          return null;
        }
      }();
    })();
  }

  public build() {
    hilog.info(0x0000, ReactInstanceManagerServiceBuilder.TAG, 'build');
    //      if (!this.mJSBundleAssetUrl && !this.mJSBundleLoader) {
    //        return;
    //      }

    let appName = "";
    let deviceName = "";

    let reactInstanceManager = new ReactInstanceManager(
      this.mJavaScriptExecutorFactory?? this.getDefaultJSExecutorFactory(appName, deviceName, null),
    this.mJSMainModulePath,
    this.mUIImplementationProvider, //?? new UIImplementationProvider(),
      this.mJSIModulesPackage?? new JSIModulePackage(),
      this.mSurfaceDelegateFactory?? null,
    this.mJSBundleLoader
    );

    ReactNativeHost.getInstance().setReactInstanceManager(reactInstanceManager)
  }

  private setJSEngine(jsInterpreter: JSInterpreter) {
    this.jsInterpreter = jsInterpreter;
  }

  private getDefaultJSExecutorFactory(appName: string, deviceName: string, reactContext: ReactContext): JavaScriptExecutorFactory {
    if (this.jsInterpreter == JSInterpreter.ARK) {
      // ArkExecutor.loadLibrary();
      return new ArkExecutorFactory();
    } else if (this.jsInterpreter == JSInterpreter.OLD_LOGIC) {
      ReactInstanceManager.initializeSoLoaderIfNecessary(reactContext);
      JSCExecutor.loadLibrary();
      return new JSCExecutorFactory(appName, deviceName);
    } else if (this.jsInterpreter == JSInterpreter.HERMES) {
      HermesExecutor.loadLibrary();
      return new HermesExecutorFactory();
    } else {
      JSCExecutor.loadLibrary();
      return new JSCExecutorFactory(appName, deviceName);
    }
  }
}
